#pragma once

#include <QString>
#include <QList>
#include <QObject>
#include <QFileInfo>
#include <QTimer>
#include <QTreeWidgetItem>
#include <QQueue>

#include "VFileData.h"
#include "VWords.h"
#include "VOutputInformation.h"
#include "VErrorWidget.h"
#include "VFolderData.h"
#include "VProjectData.h"
#include "VDirData.h"
#include "VNavigationWidget.h"

class VBackgroundSystem : public QObject
{
	Q_OBJECT
public:
	VBackgroundSystem(QObject *parent = nullptr);
	~VBackgroundSystem();
signals:
	void signals_calltip(QList<VWords*> list);
	void signals_parameter_calltip(QString str, int pos);
	void signal_mouse_hover_calltip(QString text, int pos);
	void signal_jump(QString path, int line_number);
    void signal_show_build_information(QList<VErrorWidget::VTableItem> list);
    void signal_open_file_to_display(QString path, QString text);
    void signal_update_text(QString path, QString text);
    void signal_reload_access(QString path);
    void signal_setting_moudule(QString path, QString text);
    void signal_change_symbol(QString text);
    void signal_update_keywords(QString path, int type, QStringList list);
    void signal_append_output_text(QString text);
    void signal_update_outline(QString path, QList<QTreeWidgetItem *> list);
    void signal_update_project_external_dependence(QString esln_path, QList<QTreeWidgetItem *> list);
	void signal_set_navigation(QList<VNavigationWidget::NavigationData*> list);

public slots:
    void slot_input_tip(QString path, QString line_text, int line_number, bool in_function);
    void slot_file_calltip(QString path, QString input);
    void slot_parameter_calltip(QString path, QString function_name, int parameter_pos, int show_pos);
    void slot_mouse_hover_calltip(QString path, QString pre, QString next, int line_number, bool in_function, int pos);
    void slot_jump_request(QString path, QString pre, QString next, int line_number, bool in_function);
    void slot_update_file_data(QString path, QString text);
    void slot_build(QString esln_path);
    void slot_reload_testing();
    void slot_set_file_last_time(QString path, uint time);
    void slot_reload_file(QString path);
    void slot_rename(QString old_path, QString new_path);
    void slot_select_word(QString path, VWords *word);
    void slot_open_project(QString path);
    void slot_close_project(QString path);
    void slot_reload_project(QString path);
	void slot_navigation(QString input, int type);
	void slot_delete_file(QString path);

private:

    struct VInputBlock
    {
        QString input;
        QString symbol;

        VInputBlock(QString input, QString symbol)
            :input(input),symbol(symbol){}
    };

    QList<VDirData*> _sdcc_source;
	QString _now_path;
    QString _now_dir;
    QList<VWords*> _include_dir_list;
    QList<VProjectData*> _project_list;
    QList<VFolderData*> _include_folder_list;
	QList<VFileData*> _file_data_list;
	QList<VFileData*> _now_include_file_list;
    QList<VWords*> _keyword_list;
    QList<VWords*> _template_list;
	QQueue<QString> _update_queue;
	QTimer _update_timer;

    void init_sdcc_source();
    QList<QFileInfo> search_sdcc_source_file(VFileData::VHeadFile file, char mode, bool folder=false);
    QList<QFileInfo> search_file(VProjectData *project, QString current_path, VFileData::VHeadFile file, char mode, bool folder=false);
    QList<VWords*> init_scope(QString path, int line = -1, bool in_function = false);
    void init_include_dir();
    void init_keyword();
    void init_template();
	void init_path(QString path);
    void recursion_include(VProjectData *project, QString path, QStringList & path_list);
    QStringList get_file_all_include_paths(QString path);
//	QList<QString> file_all_include_file_name(QString path);
//    QStringList get_file_current_include_paths(QString path);
	QString read_file_text(QString path);
    VProjectData* get_project_data(QString path);
	VFileData* file_data(QString path);
    VFileData* get_file_data(QString path);
    VFileData* set_file_text(QString path, QString text);
    void update_file_text(VFileData *data, QString text);
    VFileData* load_file_data(QString path);
    void update_file_include_data(VFileData *data);
    void update_all_file_include_data();
    void set_file_of_project(VFileData *data);
	QString file_path(QString file_name, QStringList search_dir_list);
    void calltip_normal(QString input, int line_number, bool in_function);
    void calltip_senior(QString input, int line_number, bool in_function);
    QList<VInputBlock> get_input_list(QString input);
    QString get_word_type(QList<VWords*> &global_scope, QString name, int line, QList<VWords*> &scope, int &level);
    VWords* get_struct(QString name, int line_number, bool in_function);
    QString text_preprocessing(QString text);
    QList<VWords*> matching_keyword(QString input);
    QList<VWords*> search_scope_word(QList<VWords *> &scope, QString text, int kind, int match, int line, int mode);
    QList<VWords*> match_expression(QList<VWords*> &global_scope, QString expression, int mode, int *change_symbol = nullptr);
    void translate_file(QString path);
    QStringList get_need_translate_files(VFileData *file);
    void translate_file(QString text, QString save_path);
    void recursion_need_translate(VFileData*file, QStringList list);
    void emit_text_to_reception(QString text);
    void emit_translate_build_error_info(QString current_path, QString text);
	QList<QTreeWidgetItem*> get_file_outline(VFileData* data, QTreeWidgetItem* parent);
    void update_file_outline(VFileData *data);
    void update_all_file_project();
    void update_file_project(VFileData *data);
    void set_file_outline(VFileData *data, QTreeWidgetItem *parent);
    QStringList get_project_external_dependence(VProjectData *project);
	void update_project_external_depandence(VProjectData *project);
	void init_update_timer();
	void update_project(VProjectData* project);
};

